package com.ltf.config;

import com.ltf.utils.JwtUtil;
import com.ltf.utils.PackJson;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

//每一次的业务请求(具体的增删改查) 1.验证 Token 是否合法，2.创建正常 Authentication(账号，权限)
public class JwtAuthenFilter extends BasicAuthenticationFilter {
    //输出语句
    private Logger logger=LoggerFactory.getLogger(this.getClass());

    //认证管理器 authenticationManager
    public JwtAuthenFilter(AuthenticationManager authenticationManager) {
        super(authenticationManager);
    }
//
    @Override //每一次内部过滤一下
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response,
                                    FilterChain chain) throws IOException, ServletException {
        //除了 api/login2外,都会到这里
        logger.debug("业务请求："+request.getServletPath());
        logger.debug("授权过滤器，获取Token，创建 认证成功的用户对象");
       //获取请求头部
        String bearer_token = request.getHeader("Authorization");
        logger.debug("Bearer="+bearer_token);

        if(bearer_token == null|| !(bearer_token.startsWith("Bearer"))){
            logger.info("第一种情形，没有token，可能访问/api/public");
            logger.info("第一种情形:无需 认证对象（账号，权限），直接放行");
            chain.doFilter(request,response);//直接放行，到下一个过滤器
            return;
        }
        String token = bearer_token.substring(7);//Bearer(6+1)
        logger.debug("token="+token);
        logger.info("第二种情形：有Token，校正Token签名，有效期");
        if (JwtUtil.isValid(token)==false){ //Token 要不签名不合法，要不过期
            logger.info("第二种情形：有Token，但是校验失败");
        logger.info("Token要不要放行，需要自己决定,看需求");
        response.setStatus(403);
        response.setContentType("application/json;charset=utf-8");
        String ret=PackJson.packJson(40304,"Token 非法","");
        response.getWriter().write(ret);
        response.flushBuffer();//刷新缓存
            return;
        }
        logger.info("第三种情形：合法Token，创建Authorization 对象，成功登录的对象");
        //Authentication authentication=authenManger.authenticate(loginToten);
        logger.info("从 Token 获取账号，角色权限，去创建一个Authentication 成功登录对象");
        String username=JwtUtil.getUsername(token);
        List<String> roles=JwtUtil.getRoles(token);
        List<SimpleGrantedAuthority> lst=new ArrayList<>();
        for (String s: roles){
            lst.add(new SimpleGrantedAuthority(s));
        }
        User user=new User(username,"",lst);
        logger.info("造一个成功登录的用户对象，必须有账号和权限");
        UsernamePasswordAuthenticationToken authention =
                new UsernamePasswordAuthenticationToken(username, null,lst);
        logger.info("吧这个成功登录的伪造对象，放在类似 Session 的结构 SecurityContextHolder");
        SecurityContextHolder.getContext().setAuthentication(authention);
        //每次业务请求，把成功登录的用户信息放在 SecurityContextHolder，表示当前登录成功
     chain.doFilter(request,response);   //放行

    }
}
